﻿using System;
using System.ComponentModel;
using System.Configuration.Install;
using System.IO;
using System.Windows.Forms;
using Microsoft.Win32;
using System.Collections.Generic;

namespace SeleniumToolkit.Install
{
    /// <summary>
    /// NUnit Addin installer
    /// </summary>
    /// <remarks>
    /// Locates the NUnit install path from the registry and copies the
    /// assembly into the bin\addins folder.
    /// 
    /// Requires that the custom action (/targetdir="[TARGETDIR]\") is passed via CustomActionData
    /// </remarks>
    [RunInstaller(true)]
    public class SeleniumNUnitAddinInstaller : Installer
    {
        private const string assemblyName = "SeleniumToolkit.NUnitAddin.dll";

        public SeleniumNUnitAddinInstaller()
        {
            #if DEBUG
            // Launch Debugger when in DEBUG
            System.Diagnostics.Debugger.Break();
            #endif
        }
        

        public override void Install(System.Collections.IDictionary stateSaver)
        {
            NUnitVersion version = NUnitVersion.Versions[TargetVersion];
            if (version.Installed)
            {
                if (!String.IsNullOrEmpty(version.AddinFolder))
                {
                    DeployAddin(version.AddinFolder);
                    
                    stateSaver.Add("nunit-addin", version.AddinFolder);
                }
            }
            
            base.Install(stateSaver);
        }

        public override void Uninstall(System.Collections.IDictionary savedState)
        {
            string addinFolder = savedState["nunit-addin"] as string;
            if (!String.IsNullOrEmpty(addinFolder))
            {
                DeleteAddin(addinFolder);
            }
            base.Uninstall(savedState);
        }

        private void DeployAddin(string nunitAddinFolder)
        {
            string sourceFileName = NUnitAddinSourcePath;
            string destFileName = Path.Combine(nunitAddinFolder, assemblyName);

            bool successful = false;

            while (!successful)
            {
                try
                {
                    File.Copy(sourceFileName, destFileName, true);
                    successful = true;
                }
                catch
                {
                    DialogResult result = MessageBox.Show("Unable to deploy nunit addin, is the addin in use?  Please close all programs referencing the addin and try again.", "File in Use", MessageBoxButtons.RetryCancel);
                    if (result == DialogResult.Cancel)
                    {
                        throw new OperationCanceledException("Installation cancelled by user.");
                    }
                }
            }
        }

        private static void DeleteAddin(string nunitAddinFolder)
        {
            string addinFileName = Path.Combine(nunitAddinFolder, assemblyName);

            while (File.Exists(addinFileName))
            {
                try
                {
                    File.Delete(addinFileName);
                }
                catch
                {
                    DialogResult result = MessageBox.Show("Unable to uninstall nunit addin, is the addin in use?  Please close all programs referencing the addin and try again.", "File in Use", MessageBoxButtons.RetryCancel);
                    if (result == DialogResult.Cancel)
                    {
                        throw new OperationCanceledException("Installation cancelled by user.");
                    }
                }
            }
        }

        private string NUnitAddinSourcePath
        {
            get
            {
                string targetDir = TargetDir;
                string sourceFileName = Path.Combine(targetDir, @"bin\" + assemblyName);

                if (!File.Exists(sourceFileName))
                {
                    throw new FileNotFoundException("Unable to locate NUnit Addin.", sourceFileName);
                }

                return sourceFileName;
            }
        }

        private string TargetVersion
        {
            get
            {
                string version = this.Context.Parameters["nunit"];
                if (String.IsNullOrEmpty(version))
                {
                    throw new ArgumentException("The installer is missing the \"nunit\" context parameter.");
                }
                return version;
            }
        }

        private string TargetDir
        {
            get
            {
                string targetDir = this.Context.Parameters["targetdir"];
                if (String.IsNullOrEmpty(targetDir))
                {
                    throw new ArgumentException("The installer is missing the \"targetdir\" context parameter.");
                }
                return targetDir;
            }
        }


    }

   


}
